<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- 
	Copyright (C) 2007, 2008, 2009, 2010, 2011. PARP Research Group.
	<http://perception.inf.um.es>
	University of Murcia, Spain.

	This file is part of the QVision library.

	QVision is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as
	published by the Free Software Foundation, version 3 of the License.

	QVision is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with QVision. If not, see <http://www.gnu.org/licenses/>.
-->

<html><head><meta http-equiv="content-Type" content="text/html;charset=UTF-8">
<title>QVision: Qt&#39;s Image, Video and Computer Vision Library</title>
<meta name="title" content="QVision" />
<meta name="dc.title" content="QVision" />
<meta name="url" content="http://perception.inf.um.es/QVision" />
<meta name="author" content="PARP Research Group - http://perception.inf.um.es" />
<meta name="revisit-after" content="30 DAYS"/>
<meta name="robots" content="index,follow"/>
<meta name="classification" content="*">
<meta name="rating" content="Safe For Kids">
<meta name="distribution" content="GLOBAL"/>
<meta name="description" content="Qt's Image, Video and Computer Vision Library"/>
<meta name="page-topic" content="Computer Vision research and prototype programming"/>
<meta name="geo.country" content="ES" />

<!--
Keywords:
By license:		open source, gnu, lgpl, gpl, free
By theme:		computer vision, image processing, robotics, programming, source, development
By usage:		library, toolkit, framework, prototype, application
By programming specs:	object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping
Interoperability with:	Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack
Functionallity:		image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface
Main data-types:	matrix, vector, tensor, quaternion, image, polyline
Video sources:		webcam, camera, stream
Devices:		embedded, desktop computer, laptop, mini-laptop
Authors:		PARP research group. University of Murcia, Spain.
-->

<meta name="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="title" content="QVision"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="tabs.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="favicon.ico" />
</head><body>

<table width="100%"><tr>
	<td><a href="http://perception.inf.um.es/"><img src="parp.png" border="0" /> <big>PARP Research Group</big></a></td>
	<td align="right"><a href="http://www.um.es/"><big>Universidad de Murcia</big> <img src="um.png" border="0" /></a></td>
</tr></table>

<hr /><br />

<table width="95%" align="center"><tr><td>

<!-- Generated by Doxygen 1.6.3 -->
<script type="text/javascript"><!--
var searchBox = new SearchBox("searchBox", "search",false,'Search');
--></script>
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
      <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li class="current"><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
          <form id="FSearchBox" action="search.php" method="get">
            <img id="MSearchSelect" src="search/search.png" alt=""/>
            <input type="text" id="MSearchField" name="query" value="Search" size="20" accesskey="S" 
                   onfocus="searchBox.OnSearchFieldFocus(true)" 
                   onblur="searchBox.OnSearchFieldFocus(false)"/>
          </form>
        </div>
      </li>
    </ul>
  </div>
  <div class="tabs">
    <ul>
      <li><a href="files.html"><span>File&nbsp;List</span></a></li>
      <li><a href="globals.html"><span>File&nbsp;Members</span></a></li>
    </ul>
  </div>
<h1>src/qvltmser/qvltmser.cpp</h1><a href="qvltmser_8cpp.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
<a name="l00002"></a>00002 <span class="comment"> *      Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012. PARP Research Group.</span>
<a name="l00003"></a>00003 <span class="comment"> *      &lt;http://perception.inf.um.es&gt;</span>
<a name="l00004"></a>00004 <span class="comment"> *      University of Murcia, Spain.</span>
<a name="l00005"></a>00005 <span class="comment"> *</span>
<a name="l00006"></a>00006 <span class="comment"> *      This file is part of the QVision library.</span>
<a name="l00007"></a>00007 <span class="comment"> *</span>
<a name="l00008"></a>00008 <span class="comment"> *      QVision is free software: you can redistribute it and/or modify</span>
<a name="l00009"></a>00009 <span class="comment"> *      it under the terms of the GNU Lesser General Public License as</span>
<a name="l00010"></a>00010 <span class="comment"> *      published by the Free Software Foundation, version 3 of the License.</span>
<a name="l00011"></a>00011 <span class="comment"> *</span>
<a name="l00012"></a>00012 <span class="comment"> *      QVision is distributed in the hope that it will be useful,</span>
<a name="l00013"></a>00013 <span class="comment"> *      but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<a name="l00014"></a>00014 <span class="comment"> *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<a name="l00015"></a>00015 <span class="comment"> *      GNU Lesser General Public License for more details.</span>
<a name="l00016"></a>00016 <span class="comment"> *</span>
<a name="l00017"></a>00017 <span class="comment"> *      You should have received a copy of the GNU Lesser General Public</span>
<a name="l00018"></a>00018 <span class="comment"> *      License along with QVision. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>
<a name="l00019"></a>00019 <span class="comment"> */</span>
<a name="l00020"></a>00020 
<a name="l00024"></a>00024 
<a name="l00025"></a>00025 <span class="preprocessor">#include &lt;<a class="code" href="qvltmser_8h.html" title="Functions to get image regions using the linear time MSER algorithm by Nister and...">qvltmser/qvltmser.h</a>&gt;</span>
<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;qvip.h&gt;</span>
<a name="l00027"></a>00027 <span class="preprocessor">#include &lt;qvipp.h&gt;</span>
<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;<a class="code" href="qvltmser__ds_8h.html" title="File from the QVision library.">qvltmser/qvltmser_ds.h</a>&gt;</span>
<a name="l00029"></a>00029 
<a name="l00030"></a>00030 <span class="comment">// &quot;ProcessStack&quot; function of original algorithm. It uses the component stack and the gray level of the last</span>
<a name="l00031"></a>00031 <span class="comment">// unstacked pixel in the boundary.</span>
<a name="l00032"></a>00032 <span class="keywordtype">void</span> processStack(QVLtmserComponentStack &amp;theQVLtmserComponentStack, uInt levelGreyBoundary)
<a name="l00033"></a>00033 {
<a name="l00034"></a>00034     <span class="keywordtype">int</span> top;
<a name="l00035"></a>00035     <span class="keywordtype">int</span> greyLevel2;
<a name="l00036"></a>00036     QVLtmserComponent *theComponentTop, *theComponent2;
<a name="l00037"></a>00037     <span class="keywordflow">while</span>(<span class="keyword">true</span>) {
<a name="l00038"></a>00038         top = theQVLtmserComponentStack.getPosTop();
<a name="l00039"></a>00039         <span class="keywordflow">if</span>(top != 0)
<a name="l00040"></a>00040             theComponent2 = (*theQVLtmserComponentStack.components)[top-1];
<a name="l00041"></a>00041         <span class="keywordflow">else</span> {
<a name="l00042"></a>00042             <span class="comment">// Just one element in stack -&gt; uprise graylevel of stack to levelGreyBoundary and return:</span>
<a name="l00043"></a>00043             theComponentTop = (*theQVLtmserComponentStack.components)[top];
<a name="l00044"></a>00044             theComponentTop-&gt;upGreyLevel(levelGreyBoundary);
<a name="l00045"></a>00045             <span class="keywordflow">break</span>;
<a name="l00046"></a>00046         }
<a name="l00047"></a>00047         greyLevel2 = theComponent2-&gt;greyLevel;
<a name="l00048"></a>00048         theComponentTop = (*theQVLtmserComponentStack.components)[top];
<a name="l00049"></a>00049         <span class="keywordflow">if</span> (levelGreyBoundary &lt; (uInt)greyLevel2) {
<a name="l00050"></a>00050             theComponentTop-&gt;upGreyLevel(levelGreyBoundary);
<a name="l00051"></a>00051             <span class="keywordflow">break</span>;
<a name="l00052"></a>00052         } <span class="keywordflow">else</span> {
<a name="l00053"></a>00053             theComponent2-&gt;addComponent(*theComponentTop,levelGreyBoundary);
<a name="l00054"></a>00054             theQVLtmserComponentStack.popComponent();
<a name="l00055"></a>00055             <span class="keywordflow">if</span> (levelGreyBoundary == (uInt)greyLevel2)
<a name="l00056"></a>00056                 <span class="keywordflow">break</span>;
<a name="l00057"></a>00057         }
<a name="l00058"></a>00058     }
<a name="l00059"></a>00059 }
<a name="l00060"></a>00060 
<a name="l00061"></a>00061 <span class="comment">// Linear-Time MSER fuction to get the list of seeds:</span>
<a name="l00062"></a><a class="code" href="group__qvmser.html#ga7270e20566a7ad57a59acb4844ca4921">00062</a> QList&lt;QVMSER&gt; <a class="code" href="group__qvmser.html#ga7270e20566a7ad57a59acb4844ca4921" title="Obtains the extracted MSER regions (QVMSER structures) using linear time MSER on...">getLTMSER</a>(<a class="code" href="classQVImage.html">QVImage&lt; uChar &gt;</a> &amp;input_image,
<a name="l00063"></a>00063                         <span class="keyword">const</span> <span class="keywordtype">int</span> minArea, <span class="keyword">const</span> <span class="keywordtype">int</span> maxArea, <span class="keyword">const</span> <span class="keywordtype">int</span> delta,
<a name="l00064"></a>00064                         <span class="keyword">const</span> <span class="keywordtype">float</span> delta_threshold, <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> downscaling)
<a name="l00065"></a>00065 {
<a name="l00066"></a>00066     <span class="keyword">static</span> QVLtmserBoundary *theQVLtmserBoundary = NULL; <span class="comment">// Structure for goundary pixels</span>
<a name="l00067"></a>00067     <span class="keyword">static</span> QVLtmserComponentStack *theQVLtmserComponentStack = NULL;
<a name="l00068"></a>00068     <span class="keyword">static</span> uInt former_width = 0, former_height = 0; <span class="comment">// Size of former image (if they change, resize structures).</span>
<a name="l00069"></a>00069     <span class="keyword">static</span> <span class="keyword">const</span> uInt greyLevels=256; <span class="comment">// Number of gray levels.</span>
<a name="l00070"></a>00070     uChar valueOfPixel;
<a name="l00071"></a>00071     <span class="keywordtype">bool</span> visited;
<a name="l00072"></a>00072     uInt currentGreyLevel, greyLevelNeighbor, indexNeighbor;
<a name="l00073"></a>00073     <span class="keywordtype">int</span> levelGreyBoundary, col = 0, row = 0, cPixel_x, cPixel_y;
<a name="l00074"></a>00074     uInt currentPixel, neighbor, pixelBoundary;
<a name="l00075"></a>00075     QVLtmserComponent *theComponentTop;
<a name="l00076"></a>00076     <a class="code" href="classQVPolyline.html" title="Polyline representation.">QVPolyline</a> aContour;
<a name="l00077"></a>00077     <a class="code" href="classQVImage.html">QVImage&lt;uChar&gt;</a> image;
<a name="l00078"></a>00078     <span class="keywordtype">int</span> minAreaScaled=minArea, maxAreaScaled=maxArea;
<a name="l00079"></a>00079 
<a name="l00080"></a>00080     <span class="keywordflow">if</span>(downscaling != 1) {
<a name="l00081"></a>00081         <a class="code" href="classQVImage.html">QVImage&lt;uChar&gt;</a> resized(input_image.<a class="code" href="classQVImage.html#ad0f2758702ee4d96d538aa353ae81bb7" title="Overloaded function from QVGenericImage::getCols().">getCols</a>()/downscaling,input_image.<a class="code" href="classQVImage.html#a55e71ad628f450ee82bb4226cb62ec17" title="Overloaded function from QVGenericImage::getRows().">getRows</a>()/downscaling);
<a name="l00082"></a>00082         <a class="code" href="group__qvippIGT.html#gafeadedf07a0e3f27bf0c39e361339e23" title="Changes an image size.This function copies the content of the ROI in the source image...">Resize</a>(input_image,resized);
<a name="l00083"></a>00083         image = resized;
<a name="l00084"></a>00084         minAreaScaled = minArea/(downscaling*downscaling);
<a name="l00085"></a>00085         maxAreaScaled = maxArea/(downscaling*downscaling);
<a name="l00086"></a>00086     } <span class="keywordflow">else</span> {
<a name="l00087"></a>00087         image = input_image;
<a name="l00088"></a>00088     }
<a name="l00089"></a>00089 
<a name="l00090"></a>00090     <span class="keyword">const</span> uInt cols = image.<a class="code" href="classQVImage.html#ad0f2758702ee4d96d538aa353ae81bb7" title="Overloaded function from QVGenericImage::getCols().">getCols</a>(), rows = image.<a class="code" href="classQVImage.html#a55e71ad628f450ee82bb4226cb62ec17" title="Overloaded function from QVGenericImage::getRows().">getRows</a>();
<a name="l00091"></a>00091 
<a name="l00092"></a>00092     <span class="keywordflow">if</span>(cols != former_width or rows != former_height) {
<a name="l00093"></a>00093         <span class="comment">// New image size; resize structures:</span>
<a name="l00094"></a>00094         <span class="keywordflow">if</span> (theQVLtmserBoundary != NULL)
<a name="l00095"></a>00095             <span class="keyword">delete</span> theQVLtmserBoundary;
<a name="l00096"></a>00096         theQVLtmserBoundary = <span class="keyword">new</span> QVLtmserBoundary(cols, rows, greyLevels);
<a name="l00097"></a>00097         <span class="keywordflow">if</span> (theQVLtmserComponentStack != NULL)
<a name="l00098"></a>00098             <span class="keyword">delete</span> theQVLtmserComponentStack;
<a name="l00099"></a>00099         theQVLtmserComponentStack = <span class="keyword">new</span> QVLtmserComponentStack(greyLevels);
<a name="l00100"></a>00100         former_width = cols;
<a name="l00101"></a>00101         former_height = rows;
<a name="l00102"></a>00102     }
<a name="l00103"></a>00103 
<a name="l00104"></a>00104     theQVLtmserComponentStack-&gt;initComponents();
<a name="l00105"></a>00105 
<a name="l00106"></a>00106     <span class="comment">// Initialize static variables of QVLtmserComponent class (to avoid unneeded intensive passing of parameters)</span>
<a name="l00107"></a>00107     QVLtmserComponent::theSeedList = QHash&lt;QPoint,QVMSER&gt;();
<a name="l00108"></a>00108     QVLtmserComponent::minArea = minAreaScaled;
<a name="l00109"></a>00109     QVLtmserComponent::maxArea = maxAreaScaled;
<a name="l00110"></a>00110     QVLtmserComponent::delta = delta;
<a name="l00111"></a>00111     QVLtmserComponent::delta_threshold = delta_threshold;
<a name="l00112"></a>00112 
<a name="l00113"></a>00113     uChar *pimage = image.<a class="code" href="classQVImage.html#a231507d781e33e508fac771b5284c3c9" title="Method to obtain image data buffer, in read/write mode.">getWriteData</a>();
<a name="l00114"></a>00114 
<a name="l00115"></a>00115     <span class="comment">// Initialize visited pixels mask. For efficiency, it will be embedded in the same image (LSB of each pixel):</span>
<a name="l00116"></a>00116     <a class="code" href="group__qvippIAALO.html#ga2f1da78d1e68b39a8462228bc78d5343" title="QVision wrapper function for IPP&amp;#39;s ippiAndC_8u_C1R.">AndC</a>(image,0xFE,image);
<a name="l00117"></a>00117 
<a name="l00118"></a>00118     <span class="keywordtype">int</span> imageStep = image.<a class="code" href="classQVImage.html#a8c5cb45d0c7fbf135d89c5cb40ed4875" title="Overloaded function from QVGenericImage::getStep().">getStep</a>();
<a name="l00119"></a>00119 
<a name="l00120"></a>00120     <span class="comment">// Initialize heap from histogram:</span>
<a name="l00121"></a>00121     QVector&lt; int &gt; histogram = <a class="code" href="group__qvipp.html#gae25c99f8b8e1975910a913eaa8d41d96" title="Calculates frequency histogram for a given set of values, for a QVImageThis function...">HistogramRange</a>(image);
<a name="l00122"></a>00122     theQVLtmserBoundary-&gt;initHeap(histogram);
<a name="l00123"></a>00123 
<a name="l00124"></a>00124     <span class="comment">// First visited pixel:</span>
<a name="l00125"></a>00125     currentGreyLevel = pimage[0] &amp; 0xFE;
<a name="l00126"></a>00126     currentPixel = 0;
<a name="l00127"></a>00127     valueOfPixel = pimage[0];
<a name="l00128"></a>00128     pimage[0] = valueOfPixel | 0x01;
<a name="l00129"></a>00129 
<a name="l00130"></a>00130     theQVLtmserComponentStack-&gt;pushComponent(currentGreyLevel,0,0);
<a name="l00131"></a>00131     <span class="keywordflow">while</span>(<span class="keyword">true</span>) { <span class="comment">// Infinite loop (until break):</span>
<a name="l00132"></a>00132         cPixel_y = (int)(currentPixel / cols);
<a name="l00133"></a>00133         cPixel_x = currentPixel - (cPixel_y * cols);
<a name="l00134"></a>00134 
<a name="l00135"></a>00135         <span class="keywordtype">char</span> nn = -1;
<a name="l00136"></a>00136         <span class="keywordflow">while</span> (nn != 3) {
<a name="l00137"></a>00137             <span class="comment">// Test next pixel (neighbour of current):</span>
<a name="l00138"></a>00138             <span class="keywordflow">if</span> (nn == -1)
<a name="l00139"></a>00139                 nn = 0;
<a name="l00140"></a>00140             <span class="keywordflow">else</span>
<a name="l00141"></a>00141                 nn++;
<a name="l00142"></a>00142             <span class="keywordflow">switch</span>(nn) {
<a name="l00143"></a>00143                 <span class="keywordflow">case</span> 0: row = cPixel_y-1; col = cPixel_x; <span class="keywordflow">break</span>;
<a name="l00144"></a>00144                 <span class="keywordflow">case</span> 1: row = cPixel_y; col = cPixel_x+1; <span class="keywordflow">break</span>;
<a name="l00145"></a>00145                 <span class="keywordflow">case</span> 2: row = cPixel_y+1; col = cPixel_x; <span class="keywordflow">break</span>;
<a name="l00146"></a>00146                 <span class="keywordflow">case</span> 3: row = cPixel_y; col = cPixel_x-1; <span class="keywordflow">break</span>;
<a name="l00147"></a>00147             }
<a name="l00148"></a>00148             <span class="keywordflow">if</span> (row &lt; 0 || col &lt; 0 || static_cast&lt;uInt&gt;(row) &gt;= rows || <span class="keyword">static_cast&lt;</span>uInt<span class="keyword">&gt;</span>(col) &gt;= cols)
<a name="l00149"></a>00149                 <span class="keywordflow">continue</span>;
<a name="l00150"></a>00150             indexNeighbor = (row*imageStep) + col;
<a name="l00151"></a>00151             valueOfPixel = pimage[indexNeighbor];
<a name="l00152"></a>00152             visited = valueOfPixel &amp; 0x01;
<a name="l00153"></a>00153             <span class="keywordflow">if</span> (visited)
<a name="l00154"></a>00154                 <span class="keywordflow">continue</span>;
<a name="l00155"></a>00155             <span class="keywordflow">else</span> {
<a name="l00156"></a>00156                 greyLevelNeighbor = pimage[indexNeighbor] &amp; 0xFE;
<a name="l00157"></a>00157                 valueOfPixel = pimage[indexNeighbor];
<a name="l00158"></a>00158                 pimage[indexNeighbor] = valueOfPixel | 0x01;
<a name="l00159"></a>00159                 <span class="keywordflow">if</span> (greyLevelNeighbor &gt;= currentGreyLevel) {
<a name="l00160"></a>00160                     <span class="comment">// If graylevel(neighbour) &gt;= graylevel(current) -&gt; move to boundary heap:</span>
<a name="l00161"></a>00161                     neighbor = (row * cols) + col;
<a name="l00162"></a>00162                     theQVLtmserBoundary-&gt;pushPixel(greyLevelNeighbor, neighbor);
<a name="l00163"></a>00163                 } <span class="keywordflow">else</span> {
<a name="l00164"></a>00164                     <span class="comment">// If graylevel(neighbour) &lt; graylevel(current) -&gt; move current pixel to heap and</span>
<a name="l00165"></a>00165                     <span class="comment">// make neighbour the current pixel. This will add a new element to the components stack,</span>
<a name="l00166"></a>00166                     <span class="comment">// and to start checking the neighbours of the new current pixel (nn=0 in next iteration):</span>
<a name="l00167"></a>00167                    theQVLtmserBoundary-&gt;pushPixel(currentGreyLevel, currentPixel);
<a name="l00168"></a>00168                    currentPixel = (row * cols) + col;
<a name="l00169"></a>00169                    cPixel_y = row;
<a name="l00170"></a>00170                    cPixel_x = col;
<a name="l00171"></a>00171                    currentGreyLevel = greyLevelNeighbor;
<a name="l00172"></a>00172                    theQVLtmserComponentStack-&gt;pushComponent(currentGreyLevel,row,col);
<a name="l00173"></a>00173                    nn = -1;
<a name="l00174"></a>00174                 }
<a name="l00175"></a>00175             }
<a name="l00176"></a>00176         }
<a name="l00177"></a>00177         <span class="comment">// We have run through every neighbour of current pixel without moving, so we must &quot;fill&quot; the pixel</span>
<a name="l00178"></a>00178         <span class="comment">// (add it to the component on the top of the stack)...</span>
<a name="l00179"></a>00179         theComponentTop = (*theQVLtmserComponentStack-&gt;components)[theQVLtmserComponentStack-&gt;getPosTop()];
<a name="l00180"></a>00180         theComponentTop-&gt;addPixel(currentGreyLevel);
<a name="l00181"></a>00181         <span class="comment">// ... then get the next pixel from the boundary heap...</span>
<a name="l00182"></a>00182         levelGreyBoundary = theQVLtmserBoundary-&gt;maxStackPr;
<a name="l00183"></a>00183         <span class="keywordflow">if</span> (levelGreyBoundary == -1 or not theQVLtmserBoundary-&gt;popPixel(levelGreyBoundary, pixelBoundary)) {
<a name="l00184"></a>00184             <span class="keywordtype">int</span> acum=0;
<a name="l00185"></a>00185             <span class="keywordflow">for</span>(uInt i=theComponentTop-&gt;greyLevelMin;i&lt;=theComponentTop-&gt;greyLevel;i++) {
<a name="l00186"></a>00186                 acum += (*theComponentTop-&gt;history)[i];
<a name="l00187"></a>00187             }
<a name="l00188"></a>00188 
<a name="l00189"></a>00189             theQVLtmserComponentStack-&gt;popComponent(); <span class="comment">// To delete last component of stack.</span>
<a name="l00190"></a>00190             <span class="keywordflow">break</span>; <span class="comment">// Get out of main &quot;while&quot; loop.</span>
<a name="l00191"></a>00191         }
<a name="l00192"></a>00192         <span class="comment">// ... and, if it applies (only if the new pixel popped out of the heap is greater than current), we</span>
<a name="l00193"></a>00193         <span class="comment">// call processStack (which keeps on filling the current &quot;hole&quot; with water):</span>
<a name="l00194"></a>00194         <span class="keywordflow">if</span> (levelGreyBoundary &gt; (<span class="keywordtype">int</span>)currentGreyLevel)
<a name="l00195"></a>00195             processStack(*theQVLtmserComponentStack, levelGreyBoundary);
<a name="l00196"></a>00196         currentPixel = pixelBoundary;
<a name="l00197"></a>00197         currentGreyLevel = levelGreyBoundary;
<a name="l00198"></a>00198     }
<a name="l00199"></a>00199 
<a name="l00200"></a>00200     QList&lt;QVMSER&gt; mser_list;
<a name="l00201"></a>00201     <span class="keywordflow">if</span>(downscaling != 1) {
<a name="l00202"></a>00202         <span class="keywordflow">foreach</span>(<a class="code" href="classQVMSER.html" title="Maximally stable extremal region datatype.">QVMSER</a> mser, QVLtmserComponent::theSeedList.values()) {
<a name="l00203"></a>00203             <span class="keywordtype">int</span> tx=downscaling*mser.<a class="code" href="classQVMSER.html#aca09ffbbcd424aaf0f6ac66d75c1f9f0" title="Seed coordinates (darkest point in region).">seed</a>.x(), ty=downscaling*mser.<a class="code" href="classQVMSER.html#aca09ffbbcd424aaf0f6ac66d75c1f9f0" title="Seed coordinates (darkest point in region).">seed</a>.y();
<a name="l00204"></a>00204             <span class="keywordtype">int</span> minvalue = input_image(tx,ty);
<a name="l00205"></a>00205             <span class="keywordflow">for</span>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0;i&lt;downscaling;i++) {
<a name="l00206"></a>00206                 <span class="keywordflow">for</span>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> j=0;j&lt;downscaling;j++) {
<a name="l00207"></a>00207                     <span class="keywordflow">if</span>(tx+i&gt;=input_image.<a class="code" href="classQVImage.html#ad0f2758702ee4d96d538aa353ae81bb7" title="Overloaded function from QVGenericImage::getCols().">getCols</a>() or ty+j&gt;=input_image.<a class="code" href="classQVImage.html#a55e71ad628f450ee82bb4226cb62ec17" title="Overloaded function from QVGenericImage::getRows().">getRows</a>())
<a name="l00208"></a>00208                         <span class="keywordflow">continue</span>;
<a name="l00209"></a>00209                     <span class="keywordflow">if</span>(input_image(tx+i,ty+j)&lt;minvalue) {
<a name="l00210"></a>00210                         minvalue = input_image(tx+i,ty+j);
<a name="l00211"></a>00211                         tx = tx+i;
<a name="l00212"></a>00212                         ty = ty+j;
<a name="l00213"></a>00213                     }
<a name="l00214"></a>00214                 }
<a name="l00215"></a>00215             }
<a name="l00216"></a>00216             mser_list.append(<a class="code" href="classQVMSER.html" title="Maximally stable extremal region datatype.">QVMSER</a>(tx,ty,mser.<a class="code" href="classQVMSER.html#a1995cf69917eb0408babaacbc4932461" title="Threshold value to obtain region.">threshold</a>,mser.<a class="code" href="classQVMSER.html#a26e76f44a74f7a71380f85d059c81b8e" title="Merit value (i.e., value of  ).">merit</a>,
<a name="l00217"></a>00217                                            mser.<a class="code" href="classQVMSER.html#a2b5dae6c4c26fb3c11d07c95dc8aa024" title="Area of region (in pixels).">area</a>*downscaling*downscaling));
<a name="l00218"></a>00218         }
<a name="l00219"></a>00219     } <span class="keywordflow">else</span> {
<a name="l00220"></a>00220         mser_list = QVLtmserComponent::theSeedList.values();
<a name="l00221"></a>00221     }
<a name="l00222"></a>00222 
<a name="l00223"></a>00223     <span class="comment">// Return seeds:</span>
<a name="l00224"></a>00224     <span class="keywordflow">return</span> mser_list;
<a name="l00225"></a>00225 }
<a name="l00226"></a>00226 
<a name="l00227"></a>00227 <span class="comment">// Function to get MSER contours from seeds, using IPP floodfill on input image:</span>
<a name="l00228"></a><a class="code" href="group__qvmser.html#ga63a38297183386411e250f0a2d52122b">00228</a> QList&lt;QVPolyline&gt; <a class="code" href="group__qvmser.html#ga63a38297183386411e250f0a2d52122b" title="Obtains the MSER (linear time MSER) contours corresponding to a list of given QVMSER...">getLTMSERContours</a>(<a class="code" href="classQVImage.html">QVImage&lt; uChar &gt;</a> &amp;input_image,QList&lt;QVMSER&gt; mser_list)
<a name="l00229"></a>00229 {
<a name="l00230"></a>00230     <a class="code" href="classQVImage.html">QVImage&lt; uChar &gt;</a> not_image;
<a name="l00231"></a>00231 
<a name="l00232"></a>00232     <a class="code" href="group__qvippIAALO.html#ga0f76ac931b05682dd833a75b8854e805" title="Performs corresponding bitwise logical operation between pixels of two image (AndC...">Not</a>(input_image,not_image);
<a name="l00233"></a>00233     QList&lt;QVPolyline&gt; output_contours;
<a name="l00234"></a>00234     <span class="keywordflow">foreach</span> (<a class="code" href="classQVMSER.html" title="Maximally stable extremal region datatype.">QVMSER</a> mser, mser_list) {
<a name="l00235"></a>00235         <a class="code" href="classQVPolyline.html" title="Polyline representation.">QVPolyline</a> polyline = getConnectedSetBorderContourThreshold(not_image,mser.<a class="code" href="classQVMSER.html#aca09ffbbcd424aaf0f6ac66d75c1f9f0" title="Seed coordinates (darkest point in region).">seed</a>, 255-mser.<a class="code" href="classQVMSER.html#a1995cf69917eb0408babaacbc4932461" title="Threshold value to obtain region.">threshold</a>);
<a name="l00236"></a>00236         output_contours.append(polyline);
<a name="l00237"></a>00237     }
<a name="l00238"></a>00238     <span class="keywordflow">return</span> output_contours;
<a name="l00239"></a>00239 }
<a name="l00240"></a>00240 
<a name="l00241"></a>00241 <span class="comment">// Linear-Time MSER fuction to get the final contours, first obtaining seeds, then filling to get contours:</span>
<a name="l00242"></a><a class="code" href="group__qvmser.html#gab466e9a127e115618bb46f4515d4d8b4">00242</a> QList&lt;QVPolyline&gt; <a class="code" href="group__qvmser.html#ga63a38297183386411e250f0a2d52122b" title="Obtains the MSER (linear time MSER) contours corresponding to a list of given QVMSER...">getLTMSERContours</a>(<a class="code" href="classQVImage.html">QVImage&lt; uChar &gt;</a> &amp;input_image,
<a name="l00243"></a>00243                                     <span class="keyword">const</span> <span class="keywordtype">int</span> minArea, <span class="keyword">const</span> <span class="keywordtype">int</span> maxArea, <span class="keyword">const</span> <span class="keywordtype">int</span> delta,
<a name="l00244"></a>00244                                    <span class="keyword">const</span> <span class="keywordtype">float</span> delta_threshold,
<a name="l00245"></a>00245                                    <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> downscaling)
<a name="l00246"></a>00246 {
<a name="l00247"></a>00247     QList&lt;QVMSER&gt; mser_list;
<a name="l00248"></a>00248 
<a name="l00249"></a>00249     mser_list = <a class="code" href="group__qvmser.html#ga7270e20566a7ad57a59acb4844ca4921" title="Obtains the extracted MSER regions (QVMSER structures) using linear time MSER on...">getLTMSER</a>(input_image,minArea,maxArea,delta,delta_threshold,downscaling);
<a name="l00250"></a>00250 
<a name="l00251"></a>00251     <span class="keywordflow">return</span> <a class="code" href="group__qvmser.html#ga63a38297183386411e250f0a2d52122b" title="Obtains the MSER (linear time MSER) contours corresponding to a list of given QVMSER...">getLTMSERContours</a>(input_image,mser_list);
<a name="l00252"></a>00252 }
<a name="l00253"></a>00253 
<a name="l00254"></a>00254 <span class="comment">/* Possible pending performance issues:</span>
<a name="l00255"></a>00255 <span class="comment">   1. Machine instruction to get most prioritary pixel of heap?</span>
<a name="l00256"></a>00256 <span class="comment">   2. inline functions?</span>
<a name="l00257"></a>00257 <span class="comment">*/</span>
</pre></div></div>
</td></tr></table>

<br /><hr><br />
<center><a href="http://perception.inf.um.es/QVision">QVision framework</a>.
<a href="http://perception.inf.um.es">PARP research group</a>.
Copyright &copy; 2007, 2008, 2009, 2010, 2011.</center>
<br />
</body>
</html>
